home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK2.toast / Development Kits (Disc 2) / QuickDraw GX / Programming Stuff / Sample Code / Printing Samples / Printer Drivers… / LaserWriterIIsc (New GX v1.1) / LaserSCIntf.c < prev    next >
Encoding:
Text File  |  1995-04-10  |  31.9 KB  |  994 lines  |  [TEXT/MPS ]

  1. /*----------------------------------------------------------------------------------------------
  2. FILENAME
  3.  
  4.     LaserSCIntf.c
  5.     
  6. DESCRIPTION
  7.  
  8.     This file contains routines for invoking commands within the command set provided by the 
  9.     LaserWriter SC and IISC. Routines within this file utilize the WriteData and CheckStatus
  10.     printing messages to in order to communicate with the printer. The actual SCSI code used to
  11.     perform the I/O to the printer is implemented in the SD_WriteData, SD_CheckStatus and
  12.     SD_GetDeviceStatus routines within the UniversalMessageIntf.c file.  The routines in this 
  13.     file provide a "higher level" interface to the SC/IISC by hiding the details of the SC/IISC 
  14.     commands and their implementation. 
  15.  
  16. COPYRIGHT
  17.  
  18.     Copyright Apple Computer, Inc.  1989-1992
  19.     All rights reserved.
  20.     
  21. ROUTINES IN THIS MODULE:
  22.  
  23.     interface routines:
  24.         LaserSC_OpenConn()
  25.         LaserSC_GetDeviceStatus()
  26.         LaserSC_ResetDevice()
  27.         LaserSC_GetSenseData()
  28.         LaserSC_SetPageMargins()
  29.         LaserSC_SetPageDimensions()
  30.         LaserSC_ClearBits()
  31.         LaserSC_DrawBits()
  32.         LaserSC_PrintPage()
  33.         LaserSC_QueryPrinter()
  34.         LaserSC_SetBuffandFeedMode()
  35.         LaserSC_GetTimeoutForSCSICmnd()
  36.  
  37.     
  38. -----------------------------------------------------------------------------------------------*/
  39.  
  40. // Include the standard Mac header files 
  41. #include "MacIncludes.h"
  42.  
  43. // Include the new QuickDraw GX graphics header files 
  44. #include <graphics routines.h>
  45. #include <graphics libraries.h>
  46. #include <math routines.h>
  47.  
  48. // Include the required Printing Manager header files 
  49. #include <PrintingManager.h>
  50. #include <PrintingMessages.h>
  51. #include <PrintingDrivers.h>
  52. #include <Collections.h>
  53. #include <Messages.h>
  54. #include <PrintingResTypes.h>
  55. #include <PrintingErrors.h>
  56.  
  57. #include <GXExceptions.h>
  58.  
  59. // Include the internal driver constants and types used by this module 
  60. #include "LaserSCResources.h"
  61. #include "UniversalMessageIntf.h"
  62. #include "LaserSCIntf.h"
  63.  
  64.  
  65. /*********************************************************************************
  66.  *                                         CONSTANTS                                                     *
  67.  *********************************************************************************/
  68.  
  69. // Miscellaneous constants
  70. enum
  71. {
  72.     minSCSICmndSz            = 5,            // Min. # of inquiry bytes returned by all SCSI devices
  73.  
  74.     kMaxRowBytes            = 304,        // max rowBytes supported by SC printer
  75.  
  76.     kPrintFromSCRam        = 0x0080,    //    Bit in the SCSI Print page command that sets the "print from printer RAM" attribute
  77.     kPrintContinuous        = 0x0040,    //    Bit in the SCSI Print page command that sets the "print a 8 ppm rate" attribute
  78.     kClearWhilePrinting    = 0x0020,    //    Bit in the SCSI Print page command that sets the "clear page while page is being printed" attribute
  79.  
  80.     kBuffered                = 2,            // These constants are used to set the manual feed and buffered mode of the printer
  81.     kFeed                        = 4,
  82.     kManual                    = 0x01,
  83.     kBufferedMode            = 0x10
  84. };
  85.  
  86.  
  87. /*********************************************************************************
  88.  *                                         TYPES                                                         *
  89.  *********************************************************************************/
  90.  
  91. // SCSICommData - structure that defines the layout of the SCSI version of the 'comm' resource
  92.  
  93. typedef struct
  94. {
  95.     ResType                commType;                // communications type ('sPTL')
  96.     
  97.     ProcPtr                releaseDevice;            // Pointer to C routine that can release SCSI device,
  98.                                                         // can be nil (N/A for this driver)
  99.     short                    scsiIOAttributes;        // SCSI I/O attributes applicable to data xfers (N/A for this driver)
  100.     short                    *statusByte;            // Location to store status byte from data xfer operation,
  101.                                                         // can be nil (N/A for this driver)
  102.     short                    scsiBus;                    // Number of scsi bus to which device is attached (0 = motherboard; applies to open connection call only). (N/A for this driver)
  103.     short                    deviceNum;                // Number of scsi device to open connection to (applies to open connection call only). (N/A for this driver)
  104.     long                    bytesPerChunk;            // 0 => ignored; > 0 => break data transfer into chunks
  105.                                                         // of this size (at SCSI TIB level). (N/A for this driver)
  106.     ProcPtr                acquireDevice;            // Pointer to C routine that can acquire SCSI device,
  107.                                                         // nil == use info below in standard routine (N/A for this driver)
  108.     short                    deviceKind;                // device kind to look for in reponse
  109.     short                    minLength;                // minimum additional data to get in response
  110.     short                    offsetStart;            // offset from start of returned data to look at (N/A for this driver)
  111.     Str255                searchString;            // string to search for in the response
  112. }    SCSICommData,
  113.     *SCSICommDataPtr,
  114.     **SCSICommDataHdl;
  115.  
  116.  
  117. /*********************************************************************************
  118.  *                                         DEFINES                                                         *
  119.  *********************************************************************************/
  120.  
  121. // Useful defines for doing I/O to the printer
  122.  
  123. #define    SendSCSICmnd(pCmnd, cmndSize)                                        Send_GXWriteData(pCmnd, cmndSize)
  124. #define    GetDataFromPrinter(inputBuff, numToGet, scsiChunkSize)    Send_GXGetDeviceStatus(nil, scsiChunkSize, inputBuff, numToGet, "\p")
  125. #define    SendDataToPrinter(outputBuff, numToSend, scsiChunkSize)    Send_GXCheckStatus(outputBuff, numToSend, scsiChunkSize, kDrvrCreatorType)
  126. #define    GetLastSCSIStatus(lastStatus)                                        Send_GXGetDeviceStatus(nil, 0, nil, lastStatus, "\p")
  127.  
  128.  
  129. /***************************************************************************************
  130. *                                         INTERNAL ROUTINES                                                     *
  131. ***************************************************************************************/                        
  132.  
  133. /********************************************************************************************
  134.  
  135.                                         EqlByteStream
  136.     function:
  137.                 EqlByteStream compares two byte streams, for a specified number of characters, to 
  138.                 determine if they are equal. 
  139.     
  140.     parameters:
  141.                 stream1                    Pointer to first byte stream
  142.                 stream2                    Pointer to second byte stream
  143.                 bytesToChk                Number of bytes to compare in the two streams
  144.     
  145.     returns:
  146.                 EqlByteStream            Returns true if byte strings equal; false otherwise
  147.                     
  148. ********************************************************************************************/
  149. Boolean EqlByteStream(Ptr stream1, Ptr stream2, short bytesToChk)
  150. {
  151.     Boolean    theyMatch = true;
  152.     
  153.     // Assume streams will match initially
  154.     
  155.     for (; bytesToChk > 0; --bytesToChk)
  156.     {
  157.         if (*stream1++ != *stream2++)    // T => Streams don't match
  158.         {
  159.             theyMatch = false;
  160.             break;
  161.         }
  162.     }
  163.     
  164.     return(theyMatch);
  165. }
  166. /* EqlByteStream */
  167.  
  168.  
  169. /********************************************************************************************
  170.  
  171.                                         DeviceIsSCPrinter
  172.     function:
  173.                 DeviceIsSCPrinter queries the specified SCSI device to determine if it's a
  174.                 SC/IISC printer. If is, it returns true; otherwise it returns false.  The
  175.                 device to query is specified by the 
  176.     
  177.     parameters:
  178.                 scsiCommData    Handle to the 'comm' resource in the target DTP file
  179.     
  180.     returns:
  181.                 Boolean            Returns true if selected device is a SC/IISC printer; false otherwise
  182.                     
  183. ********************************************************************************************/
  184. Boolean DeviceIsSCPrinter(SCSICommDataHdl scsiCommData)
  185. {
  186.     OSErr                    anErr;
  187.     SCInquiryData        queryData;
  188.     Boolean                isOurPrinter = false;
  189.     short                    amntInqData;
  190.     
  191.     // Query the device to determine if it's a printer
  192.     
  193.     anErr = LaserSC_QueryPrinter(&queryData, minSCSICmndSz);
  194.     require(anErr == noErr, QueryPrinterFails1);
  195.     
  196.     // Device responded. Now see how much more data we can read from the device
  197.     
  198.     amntInqData = queryData.additionalLength + minSCSICmndSz;
  199.     if (amntInqData > sizeof(SCInquiryData)) // T => Only read max. bytes query record can hold
  200.         amntInqData = sizeof(SCInquiryData);
  201.         
  202.     // Now read as much of the query data as we can from the device
  203.     
  204.     anErr = LaserSC_QueryPrinter(&queryData, amntInqData);
  205.     require(anErr == noErr, QueryPrinterFails2);
  206.  
  207.     // Finally we can determine if the device is an SC/IISC
  208.     {
  209.         SCSICommDataPtr    pCommData = *scsiCommData;
  210.         
  211.         if (queryData.peripheralType == pCommData->deviceKind)    // T => Responding device is a printer
  212.         {
  213.             if (queryData.additionalLength >= pCommData->minLength)    // T => Device gave us enough additional query data
  214.             {
  215.                 // Do the device product names match? 
  216.                 isOurPrinter = EqlByteStream(    ((Ptr) &queryData) + pCommData->offsetStart, 
  217.                                                         (Ptr)(&pCommData->searchString[1]), 
  218.                                                         pCommData->searchString[0]);
  219.             }
  220.         }
  221.     }
  222.     
  223.     
  224. /******* Clean-up *******/
  225.  
  226. QueryPrinterFails2:
  227. QueryPrinterFails1:
  228.     return(isOurPrinter);
  229. }
  230. /* DeviceIsSCPrinter */
  231.  
  232.  
  233. /***************************************************************************************
  234. *                                         INTERFACE ROUTINES                                                     *
  235. ***************************************************************************************/                        
  236.  
  237. /********************************************************************************************
  238.  
  239.                                         LaserSC_OpenConnection
  240.     function:
  241.                 This routine establishes a connection to the LaserWriter SC/IISC referenced 
  242.                 in the current Job.  To determine which SCSI device number to use, we 
  243.                 extract the 'comm' resource from the target Desktop Printer file and use
  244.                 the deviceNum field in the SCSICommData handle that is returned.
  245.                 
  246.                 If LaserSC_OpenConnection is successful, the client should always call 
  247.                 LaserSC_SetPageMargins and LaserSC_SetPageDimensions to ensure the printer's 
  248.                 page buffer is properly initialized. Failure to call these routines could 
  249.                 reduce the life of the printing engine.
  250.  
  251.     parameters:
  252.                 None
  253.                     
  254.     returns:
  255.                 OSErr
  256.                     
  257. ********************************************************************************************/
  258. OSErr LaserSC_OpenConnection()
  259. {
  260.     OSErr                    anErr;
  261.     SpecGlobalsHdl     hGlobals = GetMessageHandlerInstanceContext();
  262.     Str31                    printerName;
  263.     SCSICommDataHdl    scsiCommData;
  264.  
  265.     // Get the name of the target desktop printer
  266.     
  267.     GXGetPrinterName(GXGetJobOutputPrinter(GXGetJob()), printerName);
  268.     
  269.     // Now extract the SCSI 'comm' resource to get at the device number
  270.     
  271.     anErr = GXFetchDTPData(printerName, gxDeviceCommunicationsType, gxDeviceCommunicationsID, (Handle *) &scsiCommData);
  272.     require(anErr == noErr, FetchDTPData);
  273.     
  274.     // Set the deviceNum field in the globals to be the device we want to access
  275.     (*hGlobals)->deviceNum = (*scsiCommData)->deviceNum;
  276.     
  277.     // Is the target device a LaserWriter SC/IISC printer?
  278.     if ( !DeviceIsSCPrinter(scsiCommData) )
  279.         anErr = gxAioCantFindDevice;
  280.  
  281.     // Dump the resource handle we fetched
  282.     DisposeHandle((Handle) scsiCommData);
  283.     
  284.     check(anErr == noErr);
  285.  
  286.     
  287. /******* Clean-up *******/
  288.  
  289. FetchDTPData:
  290.     return(anErr);
  291. }
  292. /* LaserSC_OpenConnection */
  293.  
  294.  
  295. /********************************************************************************************
  296.  
  297.                                         LaserSC_GetDeviceStatus
  298.     function:
  299.                 LaserSC_GetDeviceStatus queries the printer to determine if it's ready to print.
  300.                 It returns a deviceStatus parameter which indicates the current readiness state of
  301.                 the device (kGoodCondition, kCheckCondition, or kBusy). If the device is in a
  302.                 check condition state, the client can call LaserSC_GetSenseData to determine the 
  303.                 exact reason why the device isn't ready.
  304.  
  305.     parameters:
  306.                 deviceStatus        Returns the current status of the device
  307.     
  308.     returns:
  309.                 OSErr
  310.                     
  311. ********************************************************************************************/
  312. OSErr LaserSC_GetDeviceStatus(short *deviceStatus)
  313. {
  314.     OSErr            anErr;
  315.     short            scsiCommand[3];
  316.     long            cmndSz;
  317.     long            lastStatus;
  318.     
  319.     // Set up the test for ready SCSI command to be sent to the printer
  320.     
  321.     scsiCommand[0] = kSCPrinterReady;
  322.     scsiCommand[1] = kSCReserved;
  323.     scsiCommand[2] = kSCReserved;
  324.     cmndSz             = 6;
  325.     
  326.     // Send the SCSI command to the device
  327.     
  328.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  329.     require(anErr == noErr, SendSCSICmndFails);
  330.     
  331.     // Now fetch the last status of the device
  332.     
  333.     anErr = GetLastSCSIStatus(&lastStatus);
  334.     require(anErr == noErr, GetLastSCSIStatusFails);
  335.     
  336.     // Return the last status
  337.     *deviceStatus = lastStatus;
  338.         
  339.  
  340. /******* Clean-up *******/
  341.  
  342. GetLastSCSIStatusFails:
  343. SendSCSICmndFails:
  344.     return(anErr);
  345. }
  346. /* LaserSC_GetDeviceStatus */
  347.  
  348.  
  349. /********************************************************************************************
  350.  
  351.                                         LaserSC_ResetDevice
  352.     function:
  353.                 LaserSC_ResetDevice will reset the LaserWriter SC/IISC to its default power-up
  354.                 state (without performing the power-up diagnostics).
  355.                     
  356.     parameters:
  357.                 none    
  358.                 
  359.     returns:
  360.                 OSErr
  361.                     
  362. ********************************************************************************************/
  363. OSErr LaserSC_ResetDevice()
  364. {
  365.     OSErr        anErr;
  366.     short        scsiCommand[3];
  367.     long        cmndSz;
  368.     
  369.     // Set up the reset SCSI command to be sent to the printer
  370.     
  371.     scsiCommand[0] = kSCResetPrinter;
  372.     scsiCommand[1] = kSCReserved;
  373.     scsiCommand[2] = kSCReserved;
  374.     cmndSz             = 6;
  375.     
  376.     // Send the SCSI command to the device
  377.     
  378.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  379.     require(anErr == noErr, SendSCSICmndFails);
  380.  
  381.  
  382. /******* Clean-up *******/
  383.  
  384. SendSCSICmndFails:
  385.     return(anErr);
  386. }
  387. /* LaserSC_ResetDevice */
  388.  
  389.  
  390. /********************************************************************************************
  391.  
  392.                                         LaserSC_GetSenseData
  393.     function:
  394.                 LaserSC_GetSenseData returns the sense data for the printer which reflects the
  395.                 last "Check Condition" status. This call is useful to determine the current 
  396.                 state of the hardware and the result of the last executed command. A structure
  397.                 of type SCSenseData is returned which contains all state information
  398.                 available from the printer.
  399.                         
  400.     parameters:
  401.                 senseData            Pointer to a SCSenseData record in which to store the 
  402.                                         the current status information.
  403.     
  404.     returns:
  405.                 OSErr
  406.                     
  407. ********************************************************************************************/
  408. OSErr LaserSC_GetSenseData(SCSenseDataPtr senseData)
  409. {
  410.     OSErr        anErr;
  411.     short        scsiCommand[3];
  412.     long        cmndSz;
  413.     long        responseSz;
  414.     
  415.     // Validate the pointer parameter
  416.     check(senseData != nil);
  417.     
  418.     // Set up the request sense SCSI command to be sent to the printer
  419.     
  420.     scsiCommand[0] = kSCRequestSense;
  421.     scsiCommand[1] = kSCReserved;
  422.     scsiCommand[2] = sizeof(SCSenseData) << 8;        // High byte contains number of bytes to read
  423.     cmndSz             = 6;
  424.     
  425.     // Send the SCSI command to the device
  426.     
  427.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  428.     require(anErr == noErr, SendSCSICmndFails);
  429.  
  430.     // Now read the request sense data from the device
  431.     
  432.     responseSz = sizeof(SCSenseData);
  433.  
  434.     anErr = GetDataFromPrinter((Ptr) senseData, &responseSz, responseSz);
  435.     require(anErr == noErr, GetDataFromPrinterFails);
  436.     
  437.     
  438. /******* Cleanup *******/
  439.  
  440. GetDataFromPrinterFails:
  441. SendSCSICmndFails:
  442.     return(anErr);
  443. }
  444. /* LaserSC_GetSenseData */
  445.  
  446.  
  447. /********************************************************************************************
  448.  
  449.                                         LaserSC_SetPageMargins
  450.     function:
  451.                 LaserSC_SetPageMargins sets the page margins associated with the page buffer
  452.                 maintained by the printer. These margins should always be set when the printer
  453.                 is powered on in order to ensure that imaging doesn't occur off the paper.
  454.                 Imaging outside of the paper can reduce the life of the laser printing engine.
  455.                 These margins define the top and left margins of the imageable area of the page.
  456.                 
  457.                 This routine accepts two parameters, which represent the top margin and the
  458.                 left margin of the page. The top margin specifies the number of lines from 
  459.                 the top of the page, where each line is 1/300 of an inch. The top margin 
  460.                 should never be set to less that 0x76 or .197 inches. The left margin
  461.                 specifies the width of the left margin in bytes (byte = 8/300th inch). 
  462.                 Incrementing or decrementing this field by one adjusts the left margin by 
  463.                 8/300th inch. The left margin should not be set to less that .197 inches.
  464.                 
  465.                 To calculate the left margins for a new paper size, keep in mind the paper is
  466.                 fed into the printer center justified. This means if the width of the paper 
  467.                 decreases by .5 inches, the Left Margin would be increased by only .25 inches.
  468.                     
  469.     parameters:
  470.                 leftMargin            Left margin of the printer's page 
  471.                 topMargin            Top margin of the printer's page 
  472.     
  473.     returns:
  474.                 OSErr
  475.                     
  476. ********************************************************************************************/
  477. OSErr LaserSC_SetPageMargins(short leftMargin, short topMargin)
  478. {
  479.     OSErr            anErr;
  480.     short            scsiCommand[3];
  481.     long            cmndSz;
  482.     long            dataSz;
  483.     short            params[2];
  484.     
  485.     // Validate the parameters to ensure they aren't too small
  486.     check((topMargin >= kMinSCTopMargin) && (leftMargin >= kMinSCLeftMargin));
  487.     
  488.     // Set up the format SCSI command to be sent to the printer
  489.     
  490.     scsiCommand[0] = kSCFormatMargin;
  491.     scsiCommand[1] = kSCReserved;
  492.     scsiCommand[2] = 0x0400;                // High byte contains the length of the parameters being sent (4 = 2 * sizeof(short))
  493.     cmndSz             = 6;
  494.     
  495.     // Send the SCSI command to the device
  496.     
  497.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  498.     require(anErr == noErr, SendSCSICmndFails);
  499.  
  500.     // Send the parameters to the set margins command on to the device
  501.     
  502.     params[0]     = topMargin;        
  503.     params[1]     = leftMargin;
  504.     dataSz         = 4;
  505.     anErr = SendDataToPrinter((Ptr) params, dataSz, dataSz);
  506.     require(anErr == noErr, SendDataToPrinterFails);
  507.     
  508.     
  509. /******* Cleanup *******/
  510.  
  511. SendDataToPrinterFails:
  512. SendSCSICmndFails:
  513.     return(anErr);
  514. }
  515. /* LaserSC_SetPageMargins */
  516.  
  517.  
  518. /********************************************************************************************
  519.  
  520.                                         LaserSC_SetPageDimensions
  521.     function:
  522.                 LaserSC_SetPageDimensions sets the page dimensions associated with the page buffer
  523.                 maintained by the printer. These dimensions should always be set when the printer
  524.                 is powered on in order to ensure that imaging doesn't occur off the paper.
  525.                 Imaging outside of the paper can reduce the life of the laser printing engine.
  526.                 These dimensions define the number of lines per page and the number of bytes
  527.                 per line. 
  528.                 
  529.                 LaserSC_SetPageDimensions accepts two parameters, the number of bytes per line
  530.                 and the number of scan lines per page. The byes per line parameter specifies
  531.                 the width of the image in bytes, where each byte represents 8/300th of an
  532.                 inch (8 pixels). This parameter must be an even number and cannot be greater
  533.                 that 304. The number of scan lines per page parameter specifies the length
  534.                 of the image in lines, where each line represents 1/300th of an inch
  535.                 (1 pixel height).
  536.                 
  537.                 These two parameters define the dimensions of an image whose top left
  538.                 corner is assumed to start at coordinate (0, 0). Positive coordinates increase
  539.                 downward and to the right. All drawing will take place within the rectangle:
  540.                 (0, 0, (Bytes per line) * 8, Number of Lines).
  541.                 
  542.     parameters:
  543.                 bytesPerScanLine    Number of bytes within each line of the page 
  544.                 numScanLines        Number of lines within the page 
  545.     
  546.     returns:
  547.                 OSErr
  548.                     
  549. ********************************************************************************************/
  550. OSErr LaserSC_SetPageDimensions(short bytesPerScanLine, short numScanLines)
  551. {
  552.     OSErr        anErr;
  553.     short        scsiCommand[3];
  554.     long        cmndSz;
  555.     long        dataSz;
  556.     short        params[2];
  557.     
  558.     // Make sure the parameters are within tolerance
  559.     check(((bytesPerScanLine % 2) == 0) && (bytesPerScanLine <= kMaxRowBytes));
  560.     
  561.     // Set up the format SCSI command to be sent to the printer
  562.     
  563.     scsiCommand[0] = kSCFormatImage;
  564.     scsiCommand[1] = kSCReserved;
  565.     scsiCommand[2] = 0x0400;                // High byte contains the length of the parameters being sent (4 = 2 * sizeof(short))
  566.     cmndSz = 6;
  567.     
  568.     // Send the SCSI command to the device
  569.     
  570.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  571.     require(anErr == noErr, SendSCSICmndFails);
  572.     
  573.     // Send the parameters to the set dimensions command on to the device
  574.     
  575.     params[0]     = bytesPerScanLine;        
  576.     params[1]     = numScanLines;
  577.     dataSz         = 4;
  578.     anErr = SendDataToPrinter((Ptr) params, dataSz, dataSz);
  579.     require(anErr == noErr, SendDataToPrinterFails);
  580.  
  581.  
  582. /******* Cleanup *******/
  583.  
  584. SendDataToPrinterFails:
  585. SendSCSICmndFails:
  586.     return(anErr);
  587. }
  588. /* LaserSC_SetPageDimensions */
  589.  
  590.  
  591. /********************************************************************************************
  592.  
  593.                                         LaserSC_ClearBits
  594.     function:
  595.                 LaserSC_ClearBits will clear all bits inside the printers page buffer defined
  596.                 by the specified rectangle. This command only applies to printers with one 
  597.                 megabyte of RAM installed. If this command is issued with bufferred mode in 
  598.                 effect (see routine below), the clear command will return immediately, before
  599.                 clearing begins. While the area is being cleared, the printer will not be 
  600.                 able to accept SCSI comands and will return a Device Busy status when
  601.                 queried.
  602.                     
  603.     parameters:
  604.                 rectToClear            Rectangle within the page buffer to clear
  605.     
  606.     returns:
  607.                 OSErr
  608.                     
  609. ********************************************************************************************/
  610. OSErr LaserSC_ClearBits(Rect *rectToClear)
  611. {
  612.     OSErr        anErr;
  613.     short        scsiCommand[3];
  614.     long        cmndSz;
  615.     long        dataSz;
  616.     short        params[4];
  617.     
  618.     // Set up the clear bits SCSI command to be sent to the printer
  619.     
  620.     scsiCommand[0] = kSCClearBits;
  621.     scsiCommand[1] = kSCReserved;
  622.     scsiCommand[2] = 0x0800;                // High byte contains the length of the parameters being sent (8 = 4 * sizeof(short))
  623.     cmndSz             = 6;
  624.     
  625.     // Send the SCSI command to the device
  626.     
  627.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  628.     require(anErr == noErr, SendSCSICmndFails);
  629.     
  630.     // Send the parameters to the clear bits command on to the device
  631.     
  632.     params[0]     =     rectToClear->left;
  633.     params[1]     =     rectToClear->top;
  634.     params[2]     =     rectToClear->right;
  635.     params[3]     =     rectToClear->bottom;
  636.     dataSz         =     8;
  637.     anErr = SendDataToPrinter((Ptr) params, dataSz, dataSz);
  638.     require(anErr == noErr, SendDataToPrinterFails);
  639.  
  640.     // Now we must wait until the device is no longer busy
  641.     {
  642.         short        deviceStatus;        
  643.     
  644.         do
  645.         {
  646.             // Get the latest status info from the printer
  647.             
  648.             anErr = LaserSC_GetDeviceStatus(&deviceStatus);
  649.             require(anErr == noErr, LaserSC_GetDeviceStatusFails);
  650.             
  651.             // Let the client app have a chance to run
  652.             anErr = GXJobIdle();
  653.             require(anErr == noErr, JobIdleFails);
  654.         }
  655.         while (deviceStatus == kBusy);
  656.     }
  657.     
  658.  
  659. /******* Cleanup *******/
  660.  
  661. JobIdleFails:
  662. LaserSC_GetDeviceStatusFails:
  663. SendDataToPrinterFails:
  664. SendSCSICmndFails:
  665.     return(anErr);
  666. }
  667. /* LaserSC_ClearBits */
  668.  
  669.  
  670. /********************************************************************************************
  671.  
  672.                                         LaserSC_DrawBits
  673.     function:
  674.                     LaserSC_DrawBits transfers image data into the specified rectangular area of
  675.                     the printer's page buffer using one of several QuickDraw transfer modes. This
  676.                     command only applies to printers with one megabyte of RAM installed.
  677.                     
  678.                     The routine accepts three parameters which specify the image data to transfer,
  679.                     the rectangle within the printer's page buffer in which to image the data, 
  680.                     and one of the QuickDraw transfer modes: srcCopy, srcOR, srcXOR, or srcBIC.
  681.     
  682.     parameters:
  683.                     imageData            Pointer to the data to image
  684.                     rectToDrawIn        Pointer to rectangle in which to image the data
  685.                     qdTransferMode        One of the QuickDraw transfer modes srcCopy, srcOR, srcXOR,
  686.                                             or srcBIC
  687.     
  688.     returns:
  689.                     noErr                    Success
  690.                     badIISCParam        imageData pointer is nil
  691.                     badTransferMode    invalid transfer modes passed to 
  692.                     
  693.                     Any other error codes that can be returned by the Async I/O software                        
  694.  
  695.     called from:
  696.                     LaserIISC Interface Call
  697.                     
  698. ********************************************************************************************/
  699. OSErr LaserSC_DrawBits(Ptr imageData, Rect *rectToDrawIn, short numBytesPerLine, short qdTransferMode)
  700. {
  701.     OSErr                anErr;
  702.     short                scsiCommand[3];
  703.     long                cmndSz;
  704.     long                dataSz;
  705.     short                params[5];
  706.     long                numImageLines;
  707.     
  708.     // Initially validate the parameters 
  709.     
  710.     check((imageData != nil) && (rectToDrawIn != nil));
  711.     check((qdTransferMode == srcCopy)     ||
  712.             (qdTransferMode == srcOr)         ||
  713.             (qdTransferMode == srcXor)     ||
  714.             (qdTransferMode == srcBic));
  715.     
  716.     // Set up the draw bits SCSI command to be sent to the printer
  717.     
  718.     scsiCommand[0] = kSCDrawBits;
  719.     scsiCommand[1] = kSCReserved;
  720.     scsiCommand[2] = 0x0A00;                // High byte contains the length of the parameters being sent (10 = 4 * sizeof(short) + sizeof(short))
  721.     cmndSz             = 6;
  722.     
  723.     // Send the SCSI command to the device
  724.     
  725.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  726.     require(anErr == noErr, SendSCSICmndFails);
  727.     
  728.     // Now set up to send the rectangle to draw in and the transfer mode, and send it
  729.     
  730.     params[0]     =     rectToDrawIn->left;
  731.     params[1]     =     rectToDrawIn->top;
  732.     params[2]     =     rectToDrawIn->right;
  733.     params[3]     =     rectToDrawIn->bottom;
  734.     params[4]     =     qdTransferMode;
  735.     dataSz         =     10;
  736.     anErr = SendDataToPrinter((Ptr) params, dataSz, dataSz);
  737.     require(anErr == noErr, SendDataToPrinterFails1);
  738.     
  739.     // Now set up to pass the bit image to the draw bits command
  740.     
  741.     numImageLines = rectToDrawIn->bottom - rectToDrawIn->top;
  742.     dataSz = numImageLines * numBytesPerLine;
  743.  
  744.     // Now send the bitmap. We negate the last parameter to indicate the SCSI transfer should be a blind transfer.
  745.     // Also, the SCSI transfer chunk size is set to the number of bytes in 1 scan line
  746.     
  747.     anErr = SendDataToPrinter(imageData, dataSz, -(numBytesPerLine));
  748.     require(anErr == noErr, SendDataToPrinterFails2);
  749.  
  750.  
  751. /******* Cleanup *******/
  752.  
  753. SendDataToPrinterFails2:
  754. SendDataToPrinterFails1:
  755. SendSCSICmndFails:
  756.     return(anErr);
  757. }
  758. /* LaserSC_DrawBits */
  759.  
  760.  
  761. /********************************************************************************************
  762.  
  763.                                         LaserSC_PrintPage
  764.     function:
  765.                 LaserSC_PrintPage prints the current contents of the printer's page buffer.
  766.                 As soon as the SCSI print command returns control to this routine, it
  767.                 returns to the caller.  If the printer is set for buffered mode, then when
  768.                 this routine returns the printer may still be busy printing the page.  Thus,
  769.                 if you're using the printer in buffered mode, you must make sure that the
  770.                 printer is no longer busy before you start sending data for the next page.
  771.                 
  772.                 The continuousPrint parameter can be used to attain the 8 page per minute
  773.                 rating of the IISC engine. Set this parameter to true to attain the improved
  774.                 rating. It should only be set true if the next print command will be issued
  775.                 in less than 7.4 seconds (8.7 for Legal paper). 
  776.                 
  777.                 Setting clearPage to true causes the image area in the printers memory to be
  778.                 cleared as the page is being printed. This substantially reduces the amount
  779.                 of time a client may wait for the printers page buffer to clear.
  780.     
  781.     parameters:
  782.                 continuousPrint    T => print at 8 page per minute rate; F => print normal rate
  783.                 clearPage            T => clear printers page buffer while printing; F => don't clear buffer
  784.     
  785.     returns:
  786.                 OSErr
  787.                     
  788. ********************************************************************************************/
  789. OSErr LaserSC_PrintPage(Boolean    continuousPrint, Boolean clearPage) 
  790. {
  791.     OSErr            anErr;
  792.     short            scsiCommand[3];
  793.     long            cmndSz;
  794.  
  795.     // Set up the print command to be sent to the printer
  796.     
  797.     scsiCommand[0] = kSCPrint;
  798.     scsiCommand[1] = kSCReserved;
  799.     scsiCommand[2] = kSCReserved;
  800.     
  801.     if (continuousPrint)    // T => Modify command to indicate 8 page per minute printing
  802.         scsiCommand[2] += kPrintContinuous;
  803.         
  804.     if (clearPage)    // T => Clear page while we print
  805.         scsiCommand[2] += kClearWhilePrinting;
  806.     
  807.     scsiCommand[2] += kPrintFromSCRam;    //    Always print from the printers RAM
  808.     cmndSz = 6;
  809.         
  810.     // Send the SCSI command to the device
  811.     
  812.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  813.     require(anErr == noErr, SendSCSICmndFails);
  814.     
  815.     
  816. /******* Cleanup *******/
  817.  
  818. SendSCSICmndFails:
  819.     return(anErr);
  820. }
  821. /* LaserSC_PrintPage */
  822.  
  823.  
  824. /********************************************************************************************
  825.  
  826.                                         LaserSC_QueryPrinter
  827.     function:
  828.                 LaserSC_QueryPrinter returns specific information about the printer (e.g. paper
  829.                 size, vendor, etc.). This call is useful to determine configuration information
  830.                 about the printer. A structure of type SCInquiryData is returned which 
  831.                 contains all configuration information available from the printer.
  832.                         
  833.     parameters:
  834.                 inquiryData            Pointer to a SCInquiryData record in which to store the 
  835.                                         the configuration information.
  836.                 querySize            amount of data (bytes) that should be read from device
  837.  
  838.     returns:
  839.                 OSErr
  840.                     
  841. ********************************************************************************************/
  842. OSErr LaserSC_QueryPrinter(SCInquiryDataPtr inquiryData, char querySize)
  843. {
  844.     OSErr            anErr;
  845.     short            scsiCommand[3];
  846.     long            cmndSz;
  847.     long            dataSz;
  848.     
  849.     // Set up the inquiry command to be sent to the printer as the write portion
  850.     // of a status command.
  851.     
  852.     scsiCommand[0] = kSCInquiry;
  853.     scsiCommand[1] = kSCReserved;
  854.     scsiCommand[2] = querySize << 8;        // Number of inquiry bytes to return
  855.     cmndSz = 6;
  856.  
  857.     // Send the SCSI command to the device
  858.     
  859.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  860.     require(anErr == noErr, SendSCSICmndFails);
  861.     
  862.     // Now read the query data from the device
  863.     
  864.     dataSz = querySize;
  865.     
  866.     anErr = GetDataFromPrinter((Ptr) inquiryData, &dataSz, dataSz);
  867.     require(anErr == noErr, GetDataFromPrinterFails);
  868.  
  869.  
  870. /******* Cleanup *******/
  871.  
  872. GetDataFromPrinterFails:
  873. SendSCSICmndFails:
  874.     return(anErr);
  875. }/* LaserSC_QueryPrinter */
  876.  
  877.  
  878. /********************************************************************************************
  879.  
  880.                                         LaserSC_SetBuffandFeedMode
  881.     function:
  882.                 LaserSC_SetBuffandFeedMode is used to change the manual feed and bufferred mode
  883.                 settings of the printer. Setting manualFeed to true informs the printer that 
  884.                 paper will be fed manually as opposed to automatically from the cassette.
  885.                 Setting bufferedMode to true causes the print from printer RAM and clear bits
  886.                 commands to return immediately, without waiting for the command to complete.
  887.                 If buffered mode is selected, the printer will return a device busy status 
  888.                 while the operation completes.
  889.     
  890.     parameters:
  891.                 manualFeed        T => pages will be manually fed into the printer; F => cassette fed
  892.                 bufferedMode    T => Don't wait for clear bits and print RAM commands to complete;
  893.                                     F => wait for them to complete.
  894.                                         
  895.     returns:
  896.                 OSErr
  897.                     
  898. ********************************************************************************************/
  899. OSErr LaserSC_SetBuffandFeedMode(Boolean manualFeed, Boolean bufferedMode)
  900. {
  901.     OSErr        anErr;
  902.     short        scsiCommand[3];
  903.     long        cmndSz;
  904.     long        dataSz;
  905.     char        params[12];
  906.     short        i;
  907.     
  908.     // Set up the mode select SCSI command to be sent to the printer
  909.     
  910.     scsiCommand[0] = kSCModeSelect;
  911.     scsiCommand[1] = kSCReserved;
  912.     scsiCommand[2] = 0x0C00;            // High bytes specifies # of bytes being sent to the printer
  913.     cmndSz = 6;
  914.     
  915.     // Send the SCSI command to the device
  916.     
  917.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  918.     require(anErr == noErr, SendSCSICmndFails);
  919.     
  920.     // Now set up the mode select parameters to be passed to the printer
  921.     
  922.     for (i = 0; i <= 11; i++)    //    Zero all twelve bytes initially
  923.         params[i] = 0;
  924.     
  925.     if (manualFeed)    // T => Set for manual feed mode
  926.         params[kFeed] = kManual;
  927.         
  928.     if (bufferedMode)    // T => Set for buffered mode
  929.         params[kBuffered] = kBufferedMode;
  930.     
  931.     // Now send the parameters to the printer
  932.     
  933.     dataSz = 12;
  934.     anErr = SendDataToPrinter(params, dataSz, dataSz);
  935.     require(anErr == noErr, SendDataToPrinterFails);
  936.     
  937. /******* CLean-up *******/
  938.  
  939. SendDataToPrinterFails:
  940. SendSCSICmndFails:
  941.     return(anErr);
  942. }
  943. /* LaserSC_SetBuffandFeedMode */
  944.  
  945.  
  946. /********************************************************************************************
  947.  
  948.                                         LaserSC_GetTimeoutForSCSICmnd
  949.     function:
  950.                     This routine returns the timeout that should be used in the call to SCSIComplete
  951.                     when the specified printer command is forced to complete.
  952.     
  953.     parameters:
  954.                     scsiCmnd        SCSI command to be issued to the printer (generated by another
  955.                                     LaserSCIntf.c interface routine).
  956.                     
  957.     returns:
  958.                     long            timeout (in ticks) to use for the SCSIComplete call
  959.                     
  960. ********************************************************************************************/
  961. long LaserSC_GetTimeoutForSCSICmnd(short scsiCmnd)
  962. {
  963.     long    timeout;
  964.     
  965.     switch ( scsiCmnd )
  966.     {
  967.          case kSCPrinterReady:
  968.          case kSCResetPrinter:
  969.          case kSCRequestSense:
  970.          case kSCFormatMargin:
  971.          case kSCFormatImage:
  972.          case kSCInquiry:
  973.          case kSCDrawBits:
  974.          case kSCModeSelect:
  975.          case kSCReserveUnit:
  976.          case kSCReleaseUnit:
  977.          case kSCModeSense:
  978.             timeout = 240;
  979.             break;
  980.             
  981.          case kSCClearBits:
  982.             timeout = 480;
  983.             break;
  984.             
  985.          case kSCDownLoadCode:
  986.          case kSCPrint:
  987.             timeout = 4800;
  988.             break;
  989.     }
  990.     
  991.     return(timeout);
  992. }
  993. /* LaserSC_GetTimeoutForSCSICmnd */
  994.